package com.hht.kotlineee

import kotlinx.coroutines.*
import org.junit.Test

import org.junit.Assert.*
import java.lang.IllegalArgumentException
import kotlin.system.measureTimeMillis
import kotlin.time.measureTime

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * See [testing documentation](http://d.android.com/tools/testing).
 */
class CoroutineTest01 {
    @Test
    fun test_sync() = runBlocking {
        var time = measureTimeMillis {
            val one = doOne()
            val two = doTwo()
            println("result = ${one + two}")
        }
        println("completed in $time ms")
        //26 2536ms
    }

    @Test
    fun test_async() = runBlocking {
        var time = measureTimeMillis {
            val one = async { doOne() }
            val two = async { doTwo() }
            println("result = ${one.await() + two.await()}")
        }
        println("completed in $time ms")
        //26 1542ms
    }

    @Test
    fun test_launch() = runBlocking {
        var time = measureTimeMillis {
            val one = launch { doOne() }
            one.join()
            val two = launch { doTwo() }
            two.join()
        }
        println("completed in $time ms")
        //2527 ms

        //协程调度器和协程启动模式
//        启动模式：
//        DEFAULT:协程创建后，立即开始调度，在调度前如果协程被取消，将直接进入取消响应的状态
//        CoroutineStart.ATOMIC：协程创建后，立即开始调度，协程执行到第一个挂七点之前不响应取消
//        LAZY只有协程被需要时，主动调用start,join或者await等函数时才会开始调度
//        UNDISPATCHED协程创建后立即在当前函数调用栈中执行，知道遇到第一个真正挂起的点。
        var job = async(context = Dispatchers.IO, start = CoroutineStart.UNDISPATCHED) {
            println("thread :" + Thread.currentThread().name)
        }
    }

    @Test
    fun test_coroutineScope() {
        runBlocking {
            coroutineScope {
                var job1 = launch {
                    delay(1000)
                    println("job1 finished")
                }
                val job2 = async {
                    delay(500)
                    println("job2 finished")
                    "job2 result"
//                throw IllegalArgumentException()
                }
            }
        }
    }

    private suspend fun doOne(): Int {
        delay(1000)
        return 14
    }

    private suspend fun doTwo(): Int {
        delay(1500)
        return 12
    }
}